
-------- TML Message #318 --------

Date: Thu, 20 Apr 89 14:04:07 EDT
From: ("William B. Morrison") morrison@pyr.gatech.edu
Archive-Message-Number: 318


***************************************************************************
** STAR SYSTEM DIGEST: star system generation, storage, and display.     **
** All followups on this topic should be sent to morrison@pyr.gatech.edu **
** They will be edited for clarity and resent to the Traveller Mailing   **
** List in a following digest.                                           **
***************************************************************************

Digest Editor's Notes:
- ----------------------
This is digest #3 in the continuing star system generation saga...
The subject of this digest is a summary of the previous two digests, and
this digest will be concluded with the latest release of James Perkins'
"gensec" and "mapsub" programs for generating and mapping sectors and
subsectors. Also, I wil use elipses (...) to indicate editing I have
done to shorten messages.

        --->>> Help the Star System Generation Digest! <<<---
There is a reason that this digest is a summary of the prvious two, 
namely that the only submission I received since I started coordinating
this discussion group has been James' update. Doesn't anybody
out there have anything to say about what they want in an automatic
sector, subsector, system, planet... generating/mapping system? 

The persons in these discussions are as follows:
      Rob Miracle    <rwmira01%ulkyvx.bitnet@RELAY.CS.NET>
      James Perkins  <jamesp@dadla.la.tek.com>
      Fred Schiff    <vu0141@bingvaxu.cc.binghamton.edu>

All discussion and followups should be sent to those listed above and myself
(Bill Morrison <morrison@pyr.gatech.edu>).

Also, I have a copy of the program mentioned in the digest 1 summary that
describes a planet down to the minutest detail (such as surface temp, stellar
mass, and almost *any* other piece of information you might want). If there
is any demand for this program, I'll post it in the next digest. This
program is based upon real planetary sciences. Here are the estimated 
run-times of this program on various systems:

    2-5 seconds user time on an HP9000/350
    5-30 seconds on a Sun-3/60
    4 minutes on an 8 MHz PC
    7 minutes on a normal PC

                       --------------------
                       SUMMARY OF DIGEST #1
                       --------------------

First Topic - generation of trade and X-boat routes:

There was a discussion between Fred Schiff and James Perkins about coding 
the current gensec/mapsub software system and the problems involved with 
adding trade and X-boat routes. The system given in the ORIGINAL boxed
version of Traveller uses the following table:

>                        JUMP ROUTES
>
>        World   ------- Jump  Distance -------
>        Pair    Jump-1  Jump-2  Jump-3  Jump-4
>        A-A     1       2       4       5
>        A-B     1       3       4       5
>        A-C     1       4       6       -
>        A-D     1       5       -       -
>        A-E     2       -       -       -
>        B-B     1       3       4       6
>        B-C     2       4       6       -
>        B-D     3       6       -       -
>        B-E     4       -       -       -
>        C-C     3       6       -       -
>        C-D     4       -       -       -
>        C-E     4       -       -       -
>        D-D     4       -       -       -
>        D-E     5       -       -       -
>        E-E     6       -       -       -
>
>        Copyright 1977 Game Designer's Workshop
>        Traveller, Volume 3, Worlds and Adventures, p. 2.
>
>The idea is that you have to roll or exceed the indicated number on a D6
>for a jump (aka trade) route to exist.

The discussion tried to define what requirements would necessitate trade 
and X-boat routes such as class of starport, density of inhabited worlds, 
trade classes of worlds (agri, indust, etc.). For trade routes, all worlds 
should somehow be connected (graph theory anyone?) in some manner using 
'classes' of trade routes (refer to the recent discussion in the trade 
discussion group). As for X-boat routes, that is going to be tougher since 
they have more requirements (Class of star port, supporting scout/navy 
base, and that the bases X-boats do connect to have connections to the 
rest of the subsector). Additionally, there is no rule saying that X-boat 
routes have to follow trade routes. This makes the job even harder. 
Both Fred and James thought that using graph theory was the way to go. You 
could have files list edges and vertices and with various programs do things 
like "what's the fastest/most scenic route to ...".  Another problem with 
this is scope. There could be thousands of systems in a database.

The followings is an excerpt between James and Fred on this topic:

>> containing the sector info. But its limited. Where do I put the
>> routes that ships go through. ...in the case of war or invasion
>> or general chaos I think I'd just like to know *all* the various
>> routes through the star-lanes...
>
>Ah... now you're exactly where I've been at; how to manage all this data.
>
>> ...How do I deal with it when I want an extended generation for a 
>> star system (I don't have too do that for every star, just the ones
>> I want to deal with) Last, how do the sectors fit together? Certainly
>> thats not a big problem, since you are only dealing with one at a
>> time usually, but wouldn't it be nice.
>
>Yeah, I've put a little thought into all these.

                      ------------------

Second Topic: Representation of all information in a common database

Of course, how do you store all of the information you've created about your
sector/subsector/system/planet? This database should have a mechanism for
storing any information at any scale (this includes the trade and X-boat
routes mentioned above, and anything considered important like capitals,
megacorps - there is even thought of storing world *maps* in this database
[Ed.- graphical representation takes a *large* amount of storgage space and
most of the system our readers will be using are PCs if I'm not mistaken]).

The discussion between Fred and James went like this:

>> Umph. Could use grid files, but since the maps aren't really maps, but
>> diagrams of locations that might be wasteful... Each star system
>> could have an optional text field for a paragraph of info...
>
>Paragraph of info?  Heck, I figure if someone wants to get verbose about
>anything they should be able to put a whole file of info in on anything.
>That's why I think you should be able to comment any sort of object (Sector,
>Subsector, System, Star, Planet, Moon, Etc.)
>
>Yeah, world maps would be optional, in fact I think you should be able
>to fill stuff out from the top down.  Oh, you want to look at THIS
>subsector? Quick... generate all the systems in it, stow it away.  And
>you want to look at THIS system's extended generation stuff? Quick,
>generate the expanded system data, stow it away.  Oh, a world map, QUICK,
>generate a world map at the grainy level.  This region?  Quick, generate a
>regional map... etc.

James Perkins had the following idea about the data representation:

>Concerning the database thing: not a complete solution, but how about, for
>every system you have 3 files:
>  name.sector (mainworld generated sector info)
>  name.xboats (xboats routes in sector name)
>  name.extend (additional info on world I'm interested in)
>
>One thing we want to be careful to avoid is duplicating information.  We
>should try to work out a single "Key" data item...
>
>         Name.sector     Sector name, Subsector names, and all system UWP's
>         Name.routes     Xboat, trade, and other routes
>        .expand - expanded system data for systems
>        .text - commentary on sector, subsector, systems, worlds
>        .map - world map information for individual worlds
>
Their idea here is to have one file for each sector and for each layer of
detail. 
 
This way, you could tailor the database to the scale an individual group
wants for their campaign. Lets face it, some groups don't need all that
realism, and referees don't want to create places where the players will
never go.  

Rob Miracle also has brought up the point of checking a systems data for
consistency with itself. Has he pointed out, the rules allow you to do a lot
of things that don't occur in the physical universe. Here's an excerpt from
his message:

>...Eventhough, Dinomn (or Dinome) can not exist by the rules.  I 
>am sorry, you just can't have a type 6 atmosphere when you are in orbit 
>one around an M6 Dwarf, even though the rules say you can, it is just too 
>darned cold (Something like 79 degrees Kelvin), Yes Virginia, Oxygen 
>does freeze.

Rob also pointed out that "portability" doesn't mean that everyone has
access to a Unix/VMS/"insert favorite mini here".

>For simplicity sake, we need to keep what ever format ASCII and under 80 
>characters and one line per system, but I would like to code in some 
>orbital information as well.  (My I ask alot).


                      ------------------

Third Topic: Operations on the data in the database

Here are some of the ideas that James came up with:

>We also need to talk about clever programs which operate on the data.
>I can think of lots of programs to emit postscript:
>
>     sector2ps - Sector map of systems, ala the Spinward Marches map
>     routes2ps - Sector map transparency overlay for each kind of trade
>                 route
>     extend2ps - Program to format extended information pages
>
>You'd use the above to create pages for a 3-ring binder, for example.
>
>Browsing programs (ascii output):
>
>        showsub - show a subsector map
>        showsys - show UWP of system and expansion data
>        showsysroutes - show map of vicinity around a system with routes
>
>As well as programs which do generation:
>
>        gensec - generates sectors
>        namesec - replaces "Unnamed" on everything with random names
>        expandsys - generates expanded data for a system, adds into
>                    name.expand
>        genroutes - generate automatic routes
>        annosys, annosub, annosec - add anotation text to the .expand file
>
>Maybe one big master program that gives you different windows onto the
>data, allows selections and operations via a graphics interface on a Mac
>or Sun.

Rob Miracle has modified a program for MT style output. This program is for
sector display. Here's what he says:

> I will probably post my Sector Display program soon. I have to clean it 
> up a bit.  It uses the sector format given in MT:Book 3 for the Spinward 
> Marches. The program reads this file and asks for your starting location.
> It then displays a hex map, with you world in the center and all surronding
> worlds and their UWP.  It then ask for your destination and tells you about
> it, displays any specific data and the gives passenger and trade information
> going to that world.
> Now the bad part, it is written in Turbo Pascal V4.0 or V5.0. It requires
> at least 640X400 resolution meaning you need an AT&T PC6300 or a PS/2 or
> PC with a VGA card.  Do you think there will be an interest in it? 


- -----------------------------------------------------------
End of STAR SYSTEM DIGEST #1 Summary
- -----------------------------------------------------------

                       --------------------
                       SUMMARY OF DIGEST #2
                       --------------------

First Topic - ideas for Database approach for system/etc generation:

These ideas are from Fred Schiff and James Perkins.

Purpose: provide the capability to create any number of systems at any layer
         of resolution. This includes the generation of sectors, subsectors,
         systems, planets (including asteroid belts), moons, and maps
         (planetary, regional, and local). 

Requirements:
          Any of this items should be annotated by the user. 
          Any layer should be optional.
          All data fields within the database should be of variable length.
          Avoid duplication of information.
          Fields should be delimited by a character (a la /etc/passwd)

The following are suggested files/tables for the database:
    Name.{filetype}
        .sector - UWP's, sector, subsector, and system names
        .routes - trade, xboat, other routes
        .expand - expanded system data for systems
        .text - commentary on sector, subsector, systems, worlds
        .map - world map information for individual worlds
        .key - (optional) explanation & code for each new base code,
               classification data and alegiance code used in .sector file;
               used to make explanation key box in outputs

The following are suggested programs to operate on the database:
     Postscript Output Programs:
        sector2ps - Sector map of systems, ala the Spinward Marches map
        sub2ps    - SubSector map of systems, ala Digest Group map
        routes2ps - Sector map transparency overlay for each kind of trade
                    route
        extend2ps - Program to format extended information pages

     Browsing Programs (ASCII output)
        showsub - show a subsector map
        showsys - show UWP of system and expansion data
        showsysroutes - show map of vicinity around a system with routes

     Generation Programs
        gensec - generates sectors
        namesec - replaces "Unnamed" on everything with random names
        expandsys - generates expanded data for a system, adds into
                    name.expand
        genroutes - generate automatic routes
        annosys, annosub, annosec - add anotation text to the .text file

And of course we need some sort of menu program to tie everything together.

- -----------------------------------------------------------
End of STAR SYSTEM DIGEST #2 Summary
- -----------------------------------------------------------

The following is James Perkins' latest and greatest mapsub/gensec
programs. Enjoy!

     *****   *****   *****   *****   *****   *****   *****

Here are two new revisions of old programs: gensec, and mapsub.

Gensec is a sector generator.  The new features are that it's
MegaTraveller compatible, allows you to generate a single sector at a
time, and allows you to specify system density and sector maturity with
words (rift, sparse, dense, mature, frontier, etc.).  It also has a UWP
format compatible with MegaTraveller, with the population multiplier,
gas giant and planetoid counts.  It also logs the version of the format
in the output file, so that other programs can recognize what version of
gensec output they have.  An acknowledgement goes to Fred Schiff for
supplying the changes to this program.

Mapsub is a subsector mapping program.  It takes one subsector's worth
of gensec output and turns it into a hex map of the subsector.  Two
modes of output are supported: ascii, in which the hexes are drawn with
standard ascii symbols like underscore, slash, backslash, and asterisk;
and postscript, suitable for sending to most postscript devices.  This
program has been totally rewritten and is much more maintainable,
readable, and expandable than it used to be.  It can easily be adjusted
to add other forms of output or formats of input.  Acknowledgements are
due to Fred Schiff for supplying changes to the old version of mapsub,
and to Yngve Larsson for the postscript additions.  It also fixes the
bug where the hex staggering was incompatible with the Traveller rules.

I've tested these on a Sun 3/60 running SunOS 4.0, and a VAX 11/780
running BSD.  Make sure if you run any system that uses index() in place
of strchr() or random() in place of rand() that you compile with the
- -DBSD option.  Particularly, the BSD rand() output looks very flaky and
using random() is MUCH better.  For example, an entire sector of worlds
ALL had only ODD numbers for world sizes, when I didn't use the -DBSD
option.  

If you come up with any fixes/additions/suggestions, please let me know
and I will happily graft them in.

Known Bug: The mapsub program produces postscript output which works
fine on a Data Products Laser Printer, but not on a Apple LaserWriter.
Any help? Suggestions?

So, without further ado:

# This is a shell archive.  Remove anything before this line, then
# unpack it by saving it in a file and typing "sh file".  (Files
# unpacked will be owned by you and have default permissions.)
#
# This archive contains:
# gensec.c mapsub.c mapsub.hex mapsub.pro

echo x - gensec.c
cat > "gensec.c" << '//E*O*F gensec.c//'
/*

    gensec - a simplistic traveller sector generator

    Simplistic Traveller sector generator, based on Marc Miller,
    "Traveller Sector Generator", Using Your Model 2/BIS, Challenge
    No.  25; and other Traveller material (Referee's Manual and
    issues of Traveller's Digest.)

    The format of the output of gensec is a superset of the material
    produced by Mr.  Miller's published program.  It now conforms to the
    format in the MegaTraveller Referee's Manual p.  16, except the
    travel zone has been put last similar to entries in Traveller's
    Digest.

    This program rewritten C and Unix Aug 18 1987 by James T. Perkins.
    (jamesp@dadla.la.tek.com, @uunet.uu.net:jamesp@dadla.la.tek.com)

    Additions made Mar 17 1989 by Fred Schiff
    (vu0141@bingvaxu.cc.binghamton.edu) to conform with Basic generation
    in MegaTraveller Referee's Manual.

*/
/*

Copyright 1989 James T. Perkins

	This notice and any statement of authorship must be reproduced
	on all copies.  The author does not make any warranty expressed
	or implied, or assumes any liability or responsiblity for the
	use of this software.

	Any distributor of copies of this software shall grant the
	recipient permission for further redistribution as permitted
	by this notice.	 Any distributor must distribute this software
	without any fee or other monetary gains, unless expressed written
	permission is granted by the author.

	This software or its use shall not be: sold, rented, leased,
	traded, or otherwise marketed without the expressed written
	permission of the author.

	If the software is modified in a manner creating derivative
	copyrights, appropriate legends may be placed on derivative
	work in addition to that set forth above.

	Permission is hereby granted to copy, reproduce, redistribute or
	otherwise use this software as long as the conditions above
	are met.

	All rights not granted by this notice are reserved.

*/

/* System include files */
#include <stdio.h>
#include <string.h>
#include <ctype.h>

/* Defines for various flavors of unix */
extern long time();
#ifdef BSD
    extern long srandom(), random();
#   define srand(x) ((int)srandom(x))
#   define rand() ((int)random())
#else !BSD
    extern int srand(), rand();
#endif

/*
 * The VERSION_STRING is the first part of the line which identifies
 * what format the file's data are in.  This same string is used by the
 * mapsub program to interpret the data correctly.
 * The VERSION_NUMBER is the actual version number of the data format
 * produced by this program.  Versions were as follows:
 *
 * Version	Description
 *	1	Compatible with early gensec/mapsub program.  Traveller format.
 #	2	First MegaTraveller-compatible format.
 */

#define VERSION_STRING	"#Version: "
#define VERSION_NUMBER	2

/* Local macros */
#define D2 nd(2, 6)
#define D1 d(6)
#define DM(test, dm) ((test) ? (dm) : 0)
#define limit(x, l, u) (((x) < (l)) ? (l) : (((x) > (u)) ? (u) : (x)))

/* Boolean type declaration */
typedef int bool;

/* Variables for controlling generation procedure */
int maturity = 1;	/* determines how well travelled sector is */
int density = 50;	/* stellar density for system presence */

/* Forward declarations */
char *progname;
char hexchar();

/* Machine-readable copyright notice */
#ifndef lint
char *copyright = "Copyright 1989 James T. Perkins";
#endif

main(ac, av)
int ac;
char **av;
{
    int x, y;
    int x_start = 1, x_end = 32;
    int y_start = 1, y_end = 40;
    char *ali = "Im";	/* Star system alignment */

    (void)srand(time((long *)NULL));
    progname = av[0];
    av++; ac--;

    options(ac, av, &x_start, &x_end, &y_start, &y_end, &ali);

    fprintf(stdout, "%s%d\n", VERSION_STRING, VERSION_NUMBER);
    for (x = x_start; x <= x_end; x++)
    {
        for (y = y_start; y <= y_end; y++)
        {
            if (d(100) <= density)
            {
                gensys(x, y, ali, stdout);
            }
        }
    }
    exit(0);
}

gensys(x, y, ali, fp)
int x, y;
char *ali;
FILE *fp;
{
    static char *nam = "Unnamed";
    static int giants[] = {1, 1, 2, 2, 3, 3, 4, 4, 4, 5, 5};
    static int belts[] = {1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3};
    char cla, bas, zon, tra[50], out[81];
    int siz, atm, hyd, pop, gov, law, tl, gas, pla, mul;
    bool sco, nav, mil;


    /* Starport class */
    switch (maturity) {
	case 0:
	    cla = *("AABBCCCDEEX" + D2 - 2); /* Backwater */
	    break;
	case 1:
	    cla = *("AAABBCCDEEX" + D2 - 2); /* Standard */
	    break;
	case 2:
	    cla = *("AAABBCCDEEE" + D2 - 2); /* Mature */
	    break;
	case 3:
	    cla = *("AAAABBCCDEX" + D2 - 2); /* Cluster */
	    break;
	default:
	    (void)fprintf(stderr,
		"%s: interal error - maturity out of range (%d)\n",
		progname, maturity);
	    exit(1);
    }

    /* Physical characteristics */
    siz = D2 - 2;
    atm = ((siz == 0) ? 0 : (D2 - 7 + siz));
    atm = limit(atm, 0, 15);
    hyd = D2 - 7 + siz + DM(atm < 2 || atm > 9, -4);
    hyd = ((siz < 2) ? 0 : hyd);
    hyd = limit(hyd, 0, 10);

    /* Demographics */
    pop = D2 - 2;
    gov = D2 - 7 + pop;
    gov = limit(gov, 0, 15);
    law = D2 - 7 + gov;
    law = limit(law, 0, 20);

    /* Technological level */
    tl = D1 + DM(cla == 'A', 6) + DM(cla == 'B', 4) + DM(cla == 'C', 2) +
        DM(cla == 'X', -4);
    tl = tl + DM(siz < 5, 1) + DM(siz < 2, 1);
    tl = tl + DM(atm < 4, 1) + DM(atm > 9 && atm < 15, 1);
    tl = tl + DM(hyd == 8, 1) + DM(hyd == 9, 2);
    tl = tl + DM(pop > 0 && pop < 6, 1) + DM(pop == 9, 2) +
        DM(pop == 10, 4);
    tl = tl + DM(gov == 0 || gov == 5, 1) + DM(gov == 13, -2);
    tl = limit(tl, 0, 20);

    /* System characteristics */
    mul = d(5) + ((D1 > 3) ? -1 : 4);		/* population multiplier */
    pla = ((D2 < 8) ? 0 : belts[D2 - 2]);	/* planetoid belts */
    gas = ((D2 < 5) ? 0 : giants[D2 - 2]);	/* gas giants */

    /* Travel advisories */
    zon = ((cla == 'X') ? 'R' : ' ');
    if (gov > 9 && law > 15)
      zon = *("    A   AA  AAA AAAR AARRAARRR" + 5 * (gov-10) + law-15);

    /* Bases */
    nav = (cla < 'C' && D2 > 7);
    sco = (cla < 'E' && (D2 + DM(cla == 'A', -3) + DM(cla == 'B', -2) +
        DM(cla == 'C', -1)) > 6);
    mil = (cla < 'D' && (D2 + DM(cla == 'A', -2) + DM(cla == 'B', -1)) > 7);
    bas = (nav && sco ? 'A' : (nav ? 'N' :
            (sco ? 'S' : (mil ? 'M' : ' '))));

    /* Trade classifications */
    *tra = '\0';
    if (pop > 8)
        (void)strcat(tra, "Hi ");        /* High Population */
    if (pop < 4)
        (void)strcat(tra, "Lo ");        /* Low Population */
    if (pop == 0 && gov == 0 && law == 0)
        (void)strcat(tra, "Ba ");        /* Barren */
    if (atm > 3 && atm < 10 && hyd > 3 && hyd < 9 && pop > 4 && pop < 8)
        (void)strcat(tra, "Ag ");        /* Agricultural */
    if (atm < 4 && hyd < 4 && pop > 5)
        (void)strcat(tra, "Na ");        /* Non-Agricultural */
    if (((atm > 1 && atm < 5) || atm == 7 || atm == 9) && pop > 8)
        (void)strcat(tra, "In ");        /* Industrial */
    if (pop < 7)
        (void)strcat(tra, "Ni ");        /* Non-Industrial */
    if ((atm == 6 || atm == 8) && pop > 5 && pop < 9 && gov > 3 && gov < 10)
        (void)strcat(tra, "Ri ");        /* Rich */
    if (atm > 1 && atm < 6 && hyd < 4)
        (void)strcat(tra, "Po ");        /* Poor */
    if (hyd == 0 && atm > 1)
        (void)strcat(tra, "De ");        /* Desert World */
    if (hyd == 10)
        (void)strcat(tra, "Wa ");        /* Water World */
    if (siz == 0 && atm == 0 && hyd == 0)
        (void)strcat(tra, "As ");        /* Asteroid Belt */
    else if (atm == 0)
        (void)strcat(tra, "Va ");        /* Vaccuum World */
    if (siz > 9 && atm > 0)
        (void)strcat(tra, "Fl ");        /* Fluid */
    if (atm < 2 && hyd > 0)
        (void)strcat(tra, "Ic ");        /* Ice-Capped */

    /* Create world data string */
    (void)sprintf(out,
        "%-18s %02d%02d %c%c%c%c%c%c%c-%c %c %-15s %1d%1d%1d %2s %c\n",
        nam, x, y, cla,
        hexchar(siz), hexchar(atm), hexchar(hyd), hexchar(pop),
        hexchar(gov), hexchar(law), hexchar(tl),
        bas, tra, mul, pla, gas, ali, zon);

    /* Write it out to file (or stdout) */
    (void)fwrite(out, strlen(out), 1, fp);
}

char hexchar(i)
int i;
{
    if (i < 0 || i > 34)
        return '?';
    else
        return *("0123456789ABCDEFGHJKLMNPQRSTUVWXYZ" + i);
}

int d(nsides)
int nsides;
{
    return (int)(rand() % (long)nsides + 1L);
}

int nd(ndice, nsides)
int ndice, nsides;
{
    if (ndice < 1)
    {
        return 0;
    }
    else
    {
        return nd(ndice - 1, nsides) + d(nsides);
    }
}

options(ac, av, x_start, x_end, y_start, y_end, ali)
int ac;
char **av;
int *x_start, *x_end, *y_start, *y_end;
char **ali;
{
    int sub;
    static int xstarts[] = {1,9,17,25};
    static int ystarts[] = {1,11,21,31};

    for (; ac > 0; av++, ac--)
    {
        if ((**av == '-') && ((sub = (*(*av + 1))) >= 'A') && (sub <= 'P'))
        {
            sub = sub - 'A';
            *x_start = xstarts[sub % 4];
            *y_start = ystarts[((sub > 11) ? 3 :
                ((sub > 7) ? 2 : ((sub > 3) ? 1 : 0)))];
            *x_end = *x_start + 7;
            *y_end = *y_start + 9;
        }
        else if (isdigit(**av))
	{
            density = atoi(*av);
	}
        else if (strcmp(*av, "rift") == 0)
	{
	    density = 4;
	}
        else if (strcmp(*av, "sparse") == 0)
	{
	    density = 16;
	}
	else if (strcmp(*av, "scattered") == 0)
	{
	    density = 33;
	}
	else if (strcmp(*av, "dense") == 0)
	{
            density = 66;
	}
        else if (strcmp(*av, "backwater") == 0)
	{
	    maturity = 0;
	}
        else if (strcmp(*av, "frontier") == 0)  /* Standard - default */
	{
	    maturity = 1;
	}
        else if (strcmp(*av, "mature") == 0)
	{
	    maturity = 2;
	}
        else if (strcmp(*av, "cluster") == 0)
	{
	    maturity = 3;
	}
	else if (strlen(*av) == 2 && isalpha(**av))
	{
	    *ali = *av;
	}
        else
	{
	    usage();
	}
    }
}

usage()
{
    char *usemess = "\
  Generates Traveller sector or subsector.\n\
\n\
  S = {A..P}, subsector to generate\n\
  density = generation percentage or rift|sparse|scattered|dense\n\
  maturity = backwater|frontier|mature|cluster\n\
  ac = two-letter system alignment code (first character must be alphabetic)\n\
  defaults are:\n\
    entire sector, 50%% stellar density, standard frontier maturity,\n\
    Im (Imperium) alignment.\n";

    fprintf(stderr,
	"usage: %s {-S | density | maturity | ac }\n", progname);

    fprintf(stderr, usemess);
    exit(1);
}
//E*O*F gensec.c//

echo x - mapsub.c
cat > "mapsub.c" << '//E*O*F mapsub.c//'
/*************************************************************************
 *
 * NAME
 *	mapsub - Traveller Subsector Mapper
 *
 * SYNOPSIS
 *	mapsub [ -a | -p ] < Subsector.dat
 *
 * DESCRIPTION
 *	This program takes Traveller subsector world data and converts it
 *	into a subsector map, either ascii or postscript.  Each subsector
 *	hex has the following data in it:
 *
 *	          ______
 *	         / XXYY \	<- Hex number
 *	        /  * S T \	<- *=Naval base, S=Starport class, T=Tech level
 *	       /  ^ @ .   \	<- ^=Scout base, @=Liquid world, O=Desert
 *	       \  System  /	   world, %=Asteroids, .=Gas giant presence
 *	        \  Name  /	<- System Name
 *	         \______/	<- CAPITOL, Capitol, RED, or amber travel zones
 *
 * OPTIONS
 *	-a	Produce Ascii output, like the above.  This is the default.
 *	-p	Produce Postscript output.  Looks much more like the real
 *		format published in the Spinward Marches map.
 *
 * FILES
 *	This program depends on two files being available:
 *
 *	./mapsub.hex	- contains an ascii hex grid, which is filled in
 *			  with world data by mapsub.
 *			  This file's pathname may be easily changed by
 *			  changing the MAP_TEMPLATE #define.
 *	./mapsub.pro	- contains postscript function definitions which
 *			  are needed to plot the worlds efficiently.
 *			  This file's pathname may be easily changed by
 *			  changing the PS_PROLOGUE #define.
 *	Subsector.dat	- the input file (actually this program eats whatever
 *			  it is given on its stdin).  The format can be in
 *			  one of two formats; version 1 format or version 2
 *			  format:
 *
 *	VERSION 1 format: The first line of the file is "#Version: 1".
 *	Each following line of input is 59 characters long, as follows:
 *
 *	"XXYY System_Name_______ CSAHPGL-T B Trade_Codes____ Al Z GP"
 *
 *	Version 1 is still around, so that data generated with the old
 *	version of gensec can still be used.
 *
 *	VERSION 2 format: The first line of the file is "#Version: 2".
 *	Each following line of the file is 60 characters long, as follows:
 *
 *	"System_Name_______ XXYY CSAHPGL-T B Trade_Codes____ MPG Al Z"
 *
 *	Version 2 supports most of the MegaTraveller changes, except it
 *	does not have the star information.  It is the current version of
 *	the gensec program's output.
 *
 *	Fortunately, if there are a few additional columns of data added to
 *	the right, this program can tolerate the change.
 *
 * BUGS
 *	Ascii output looks passible, but not terrific.
 *	Postscript output looks terrific, but does not indicate world capitals.
 *
 * AUTHOR
 *	James T. Perkins, jamesp@dadla.la.tek.com
 *
 * HISTORY
 *	Based on an earlier program by James Perkins.
 *	Fred Schiff (vu0141@bingvaxu.cc.binghamton.edu) added MegaTraveller
 *	capability to the original mapsub.  Yngve Larsson (yla@ida.liu.se)
 *	added postscript output to the original, and authored the mapsub.pro
 *	file.  James Perkins then rototilled the original program and made
 *	it much more modifiable, incorporating the changes by Fred and Yngve.
 *	This is now the latest version.
 *
 *	When	Who			What
 *	------	-----------------------	------------------------------------
 *	890417	jamesp@dadla.la.tek.com	Initial Release
 *
 * VERSION TRACKING
 *
 * $Header: mapsub.c,v 1.5 89/04/18 11:02:48 jamesp Exp $
 * $Locker:  $
 * 
 *************************************************************************/
/*

Copyright 1989 James T. Perkins

	This notice and any statement of authorship must be reproduced
	on all copies.  The author does not make any warranty expressed
	or implied, or assumes any liability or responsiblity for the
	use of this software.

	Any distributor of copies of this software shall grant the
	recipient permission for further redistribution as permitted
	by this notice.	 Any distributor must distribute this software
	without any fee or other monetary gains, unless expressed written
	permission is granted by the author.

	This software or its use shall not be: sold, rented, leased,
	traded, or otherwise marketed without the expressed written
	permission of the author.

	If the software is modified in a manner creating derivative
	copyrights, appropriate legends may be placed on derivative
	work in addition to that set forth above.

	Permission is hereby granted to copy, reproduce, redistribute or
	otherwise use this software as long as the conditions above
	are met.

	All rights not granted by this notice are reserved.

*/

#include <stdio.h>
#include <string.h>
#include <ctype.h>

/************************************/
/*                                  */
/*  PROGRAM IDENTIFICATION          */
/*                                  */
/************************************/

/*
 * RCS id and Copyright.
 */

#ifdef Lint
static char *rcsid = "$Header: mapsub.c,v 1.5 89/04/18 11:02:48 jamesp Exp $";
static char *copyright = "Copyright 1989 James T. Perkins";
#endif

/************************************/
/*                                  */
/*  DEFINES                         */
/*                                  */
/************************************/

#ifdef BSD
#define index strchr
#define rindex strrchr
#endif

/*
 * Modes of program operation
 */

#define M_ASCII		0
#define M_POSTSCRIPT	1
#define NUM_MODES	2

/*
 * Maximum Length of an input or output line
 */

#define LINE_SIZE	81

/*
 * MAP_TEMPLATE is the pathname of the empty hex-grid program.
 * PS_PROLOGUE is the pathname of the postscript prologue file.
 */

#ifndef MAP_TEMPLATE
#define MAP_TEMPLATE	"./mapsub.hex"
#endif MAP_TEMPLATE
#ifndef PS_PROLOGUE
#define PS_PROLOGUE	"./mapsub.pro"
#endif PS_PROLOGUE

/*
 * VERSION is the string which identifies a line containing the file
 * format version number.  This permits this program to parse and
 * recognaize different input formats.
 */

#define VERSION_STRING	"#Version: "
#define DEFAULT_VERSION 1

/************************************/
/*                                  */
/*  STRUCTS                         */
/*                                  */
/************************************/

/*
 * Entry points for different modes
 */

struct output_mode {
    char flag;		/* command-line option flag for this mode */
    void (*init)();	/* ptr to function to initialize output */
    void (*map)();	/* ptr to function to map 1 system's data */
    void (*finish)();	/* ptr to function to finish output */
};

/*
 * What composes a system...
 */

struct sys {
    char name[19];		/* System name */
    int x, y;			/* Hex location */
    char uwp[10];		/* CSAHPGL-T */
    char base;			/* S, N, A, B, or M for bases */
    char trade[16];		/* Up to 5 trade codes, space seperated */
    int pmul;			/* pop multiplier */
    int belt;			/* number of planetoid belts */
    int gas;			/* number of gas giants */
    char align[3];		/* system alignment */
    char zone;			/* travel zone: ' ', 'A', 'R' */
};

/************************************/
/*                                  */
/*  GLOBAL DATA                     */
/*                                  */
/************************************/

/*
 * Usage message
 */

char *usage = "usage: %s [ -ascii | -postscript ]\n";

/*
 * Forward declarations
 */

void bzero();
struct sys *line2system();
void ascii_init(), ascii_map(), ascii_finish();
void ps_init(), ps_map(), ps_finish();
void rem_trail_sp();
char *ascii_center_name();
void ascii_overwrite();

/*
 * The actual modes of output we support -
 * 	a - ascii mode
 *	p - postscript mode
 */

struct output_mode output[NUM_MODES] = {
    { 'a',	ascii_init,	ascii_map,	ascii_finish	},
    { 'p',	ps_init,	ps_map,		ps_finish	}
};

/*
 * program name
 */

char *progname;

/************************************/
/*                                  */
/*  FUNCTIONS                       */
/*                                  */
/************************************/

^L
/*************************************************************************
 *
 * NAME
 *	main - mainline for mapsub
 *
 * PARAMETERS
 *	ac - argument count
 *	av - array of pointers to strings containing the arguments
 *
 * DESCRIPTION
 *	Parses arguments to determine what output mode we're to be in,
 *	then initializes that output module, reads the data from stdin
 *	and maps it into the output, and finishes the output.
 *
 * RETURN VALUE
 *	int - but value is ignored
 *
 * CAVEATS
 *	None.
 *
 *************************************************************************/

main(ac, av)
int ac;
char **av;
{
    int mode;			/* indicates ASCII or POSTSCRIPT mode */
    char line[LINE_SIZE];	/* stores a line of system input */
    struct sys *system;		/* stores a system, broken down from line */

    progname = *av;
    mode = get_mode(ac, av);

    /*
     * Initialize the output mode
     */

    output[mode].init();

    /*
     * Get each line of output, stuff it into a system structure, and map it.
     */

    while (fgets(line, sizeof(line), stdin) != NULL) {
	if ((system = line2system(line)) != NULL) {
	    output[mode].map(system);
	}
    }

    /*
     * Finish up output processing
     */

    output[mode].finish();
    exit(0);
}

^L
/*************************************************************************
 *
 * NAME
 *	get_mode - parses arguments, returns the output mode
 *
 * PARAMETERS
 *	ac - argument count
 *	av - array of pointers to strings containing the arguments
 *
 * DESCRIPTION
 *	Parses the arguments and returns the output mode of the program.
 *	If no arguments are given, defaults to ascii mode.  If a bad
 *	argument is given, prints an error message and exits.
 *
 * RETURN VALUE
 *	int - M_ASCII for ascii output, M_POSTSCRIPT for postscript output,
 *	etc.
 *
 * CAVEATS
 *	Uses the output global.
 *
 *************************************************************************/

int
get_mode(ac, av)
int ac;
char **av;
{
    int mode;

    mode = M_ASCII;

    if (ac > 1) {
	mode = -1;
	if (av[1][0] == '-') {
	    for (mode = NUM_MODES - 1; mode >= 0; mode--) {
		if (av[1][1] == output[mode].flag) {
		    break;
		}
	    }
	}
    }

    if (mode == -1) {
	fprintf(stderr, usage, progname);
	exit(1);
    }

    return (mode);
}

^L
/*************************************************************************
 *
 * NAME
 *	line2system - parses an input line and returns a system structure
 *
 * PARAMETERS
 *	line - one line of uwp system data from the stdin.  Or, a
 *		comment line, empty line, or version line.
 *
 * DESCRIPTION
 *	Examines the given line, parses it into a system structure, and
 *	returns a pointer to the structure.  If the input is empty or
 *	a comment line, it ignores it.  If the input is a version line,
 *	this function remembers to parse future input consistent with that
 *	format.
 *
 * RETURN VALUE
 *	struct sys * - pointer to parsed system structure corresponding to
 *	the line of input, or NULL of the line was a comment or version
 *	number.
 *
 * CAVEATS
 *	Pointer returned is to static data.
 *	Remembers the input version between invocations.
 *
 *************************************************************************/

struct sys *
line2system(line)
char *line;
{
    static struct sys s;
    static int version = DEFAULT_VERSION;

    if (line[0] == '#' || line[0] == '\0' || line[0] == '\n') {
	/*
	 * This is a comment line of some kind.
	 */

	if (strncmp(line, VERSION_STRING, strlen(VERSION_STRING)) == 0) {
	    /*
	     * Get file format version number
	     */

	    sscanf(line, "%*s %d", &version);
	}
	return NULL;
    }

    /*
     * Zero out the system structure
     */

    bzero((char *)&s, sizeof(s));

    /*
     * Parse the line into the system struct
     */

    if (version == 1) {
	char gas = ' ', belt = ' ';

	(void)sscanf(line,
	    "%2d%2d%*c%18c%*c%9c%*c%c%*c%15c%*c%2c%*c%c%*c%1c%1c",
	    &s.x, &s.y, s.name, s.uwp, &s.base, s.trade,
	    s.align, &s.zone, &gas, &belt);
	s.gas = ((gas == 'G') ? 1 : 0);
	s.belt = ((belt == 'P') ? 1 : 0);
    }
    else if (version == 2) {
	(void)sscanf(line,
	    "%18c%*c%2d%2d%*c%9c%*c%c%*c%15c%*c%1d%1d%1d%*c%2c%*c%c",
	    s.name, &s.x, &s.y, s.uwp, &s.base, s.trade,
	    &s.pmul, &s.belt, &s.gas, s.align, &s.zone);
    }
    else {
	fprintf(stderr, "%s: Unknown input format version number %d.\n",
	    progname, version);
	exit(1);
    }

    /*
     * Null-terminate...
     */

    s.name[18] = '\0';
    s.uwp[9] = '\0';
    s.trade[15] = '\0';

    rem_trail_sp(s.name);
    rem_trail_sp(s.uwp);
    rem_trail_sp(s.trade);

    return &s;
}

^L
/*************************************************************************
 *
 * NAME
 *	rem_trail_sp - remove trailing spaces from a string
 *
 * PARAMETERS
 *	s - the string to change
 *
 * DESCRIPTION
 *	eats off trailing spaces from the given string, turning them into
 *	NULLs.
 *
 * RETURN VALUE
 *	void
 *
 * CAVEATS
 *	Changes string pointed to by its argument.
 *
 *************************************************************************/

void
rem_trail_sp(s)
char *s;
{
    int i = strlen(s) - 1;

    while (i >= 0 && s[i] == ' ') {
        s[i--] = '\0';
    }
}

^L
/*************************************************************************
 *
 * NAME
 *	bzero - zero a block of memory
 *
 * PARAMETERS
 *	s - pointer to beginning of memory area
 *	n - number of bytes to zero
 *
 * DESCRIPTION
 *	clears the given area of memory.
 *
 * RETURN VALUE
 *	void
 *
 * CAVEATS
 *	Destructive to data pointed to by the first argument
 *
 *************************************************************************/

#ifndef BSD
void
bzero(s, n)
char *s;
int n;
{
    while (n-- > 0) {
        *s++ = '\0';
    }
}
#endif

^L
/*************************************************************************
 *
 * NAME
 *	capitalize - capitalize a string
 *
 * PARAMETERS
 *	s - the string to capitalize
 *
 * DESCRIPTION
 *	converts all lower-case letters in the given string to upper-case
 *	letters.
 *
 * RETURN VALUE
 *	void
 *
 * CAVEATS
 *	Changes the data pointed to by it's input argument.
 *
 *************************************************************************/

void
capitalize(s)
char *s;
{
    for (; *s; s++) {
	if (islower(*s)) {
	    *s = toupper(*s);
	}
    }
}

/************************************/
/*                                  */
/*  ASCII FUNCTIONS                 */
/*                                  */
/************************************/

char ascii_output[70][LINE_SIZE];	/* an image of the output lines */
int ascii_n_lines = 0;			/* number of lines in ascii_output */

^L
/*************************************************************************
 *
 * NAME
 *	ascii_init - prepare for ascii mapping
 *
 * PARAMETERS
 *	None.
 *
 * DESCRIPTION
 *	Reads the map template into memory, and remembers how many lines
 *	were read in.
 *
 * RETURN VALUE
 *	void
 *
 * CAVEATS
 *	Destroys the static data space of ascii_output and ascii_n_lines.
 *
 *************************************************************************/

void
ascii_init()
{
    FILE *template;
    char *map;

    ascii_n_lines = 0;

    if ((template = fopen(MAP_TEMPLATE, "r")) == NULL) {
	perror(MAP_TEMPLATE);
	exit(1);
    }

    for (map = &ascii_output[0][0]; fgets(map, LINE_SIZE, template) != NULL;
	map += LINE_SIZE) {
	ascii_n_lines++;
    }

    (void)fclose(template);
}

#define ascii_xy(x, y, dx, dy) \
    &ascii_output[(((y) - 1) % 10) * 6 + \
    ((2 * ((x) / 2) == (x)) ? 4 : 1) + (dy)]\
    [(((x) - 1) % 8) * 9 + 1 + (dx)]

^L
/*************************************************************************
 *
 * NAME
 *	ascii_map - map a star system onto the ascii output
 *
 * PARAMETERS
 *	s - system to map
 *
 * DESCRIPTION
 *	Places the system onto the ascii_output region of memory.
 *	This is a terrible kludge.  Depends on the icky ascii_xy macro
 *	which returns memory locations to overwrite.
 *
 * RETURN VALUE
 *	void
 *
 * CAVEATS
 *	Overwrites static data space (ascii_output)
 *
 *************************************************************************/


void
ascii_map(s)
struct sys *s;
{
    char t[80], *u;

    /*
     * Plot each item onto the output image; write hex:
     *      ______
     *    &/ XXYY \        & is where the x, y offset is
     *    /  * S T \
     *   /  ^ @ .   \
     *   \  System  /
     *    \  Name  /
     *     \______/		<- CAPITOL, Capitol, RED, or Amber go here
     */

    (void)sprintf(t, "%02d%02d", s->x, s->y);
    ascii_overwrite(ascii_xy(s->x, s->y, 3, 0), t, 4);
    ascii_overwrite(ascii_xy(s->x, s->y, 3, 1), 
        ((s->base == 'N' || s->base == 'A') ? "*" : " "), 1);
    ascii_overwrite(ascii_xy(s->x, s->y, 5, 1), s->uwp, 1);
    ascii_overwrite(ascii_xy(s->x, s->y, 7, 1), &s->uwp[8], 1);
    ascii_overwrite(ascii_xy(s->x, s->y, 2, 2),
	((s->base == 'S' || s->base == 'A') ? "^" : " "), 1);
    ascii_overwrite(ascii_xy(s->x, s->y, 4, 2),
	((s->uwp[1] == '0') ? "%" : ((s->uwp[3] == '0') ? "O" : "@")), 1);
    ascii_overwrite(ascii_xy(s->x, s->y, 6, 2),
	((s->gas > 0) ? "." : " "), 1);

    u = s->trade;
    if (u = strchr(u, 'H')) {
	if (u[1] == 'i' || u[1] == 'I') {
	   capitalize(s->name);
	}
    } else if (s->uwp[4] == '9' || s->uwp[4] == 'A') {
       capitalize(s->name);
    }

    u = ascii_center_name(s->name, s->x, s->y, 0, 3, 10);
    if (u) {
	(void)ascii_center_name(u + 1, s->x, s->y, 1, 4, 8);
    }

    switch (s->zone) {
    case 'A': /* Amber */
	ascii_overwrite(ascii_xy(s->x, s->y, 2, 5), "amber", 5);
	break;
    case 'R': /* Red */
	ascii_overwrite(ascii_xy(s->x, s->y, 2, 5), "RED", 3);
	break;
    }

    u = s->trade;
    while (u = strchr(u, 'C')) {
	if (u[1] == 'a' || u[1] == 'A') {
	    ascii_overwrite(ascii_xy(s->x, s->y, 2, 5), "Capitol", 7);
	    break;
	}
	else if (u[1] == 'x' || u[1] == 'X') {
	    ascii_overwrite(ascii_xy(s->x, s->y, 2, 5), "CAPITOL", 7);
	    break;
	}
	else {
	    u++;
	}
    }
}

^L
/*************************************************************************
 *
 * NAME
 *	ascii_finish - write out the ascii output to stdout
 *
 * PARAMETERS
 *	none.
 *
 * DESCRIPTION
 *	writes the ascii_output array to stdout.
 *
 * RETURN VALUE
 *	void
 *
 * CAVEATS
 *	None.
 *
 *************************************************************************/

void
ascii_finish()
{
    int i;

    /*
     * Write out finished map
     */

    for (i = 0; i < ascii_n_lines; i++) {
        printf("%s", ascii_output[i]);
    }
}

^L
/*************************************************************************
 *
 * NAME
 *	ascii_overwrite - overwrite memory with new data
 *
 * PARAMETERS
 *	p - address to begin overwriting at
 *	s - address of string of data to overwrite with
 *	n - number of bytes to overwrite
 *
 * DESCRIPTION
 *	Overwrites the section of memory at p with the first n characters
 *	of string s.
 *
 * RETURN VALUE
 *	void
 *
 * CAVEATS
 *	Destroys memory pointed to by one of it's arguments.
 *
 *************************************************************************/

void
ascii_overwrite(p, s, n)
char *p, *s;
int n;
{
    while (n-- > 0) {
        *p++ = *s++;
    }
}

^L
/*************************************************************************
 *
 * NAME
 *	ascii_center_name - place part or all of a name into ascii_output
 *
 * PARAMETERS
 *	name - name to place
 *	x, y - hex x,y location in the subsector
 *	dx, dy - screen offsets from origin of this hex's xy coords
 *	width - width of this line of output.
 *
 * DESCRIPTION
 *	Take the given name and try to place as many words as will fit in given
 *	width into the map at x, y, dx, dy.  Also center each line of output in
 *	the width.  Unfortunately, a word may be too long to fit, in which case
 *	place it anyway, overlapping.
 *
 * RETURN VALUE
 *	char * - Returns 0 if it was able to place the entire name, or a pointer
 *	to the space just following the last word placed.
 *
 * CAVEATS
 *	Nasty kludges, beware.
 *
 *************************************************************************/

char *
ascii_center_name(name, x, y, dx, dy, width)
char *name;
int x, y, dx, dy, width;
{
    char *end, *cur, *oldcur;
    int offset;

    cur = strchr(name, ' ');
    if (cur == NULL) {
        end = name + strlen(name) - 1;
    }
    else {
        end = cur - 1;
        oldcur = NULL;
        while (cur && cur - name <= width && cur != oldcur) {
            end = cur - 1;
            oldcur = cur;
            cur = strchr(cur + 1, ' ');
            if (cur == NULL) {
                cur = name + strlen(name);
            }
        }
    }
    offset = (width - (end - name + 1)) / 2;
    dx = dx + offset;
    ascii_overwrite(ascii_xy(x, y, dx, dy), name, end - name + 1);

    if (strchr(end, ' ')) {
        return end + 1;
    }
    else {
        return NULL;
    }
}

/************************************/
/*                                  */
/*  POSTSCRIPT FUNCTIONS            */
/*                                  */
/************************************/

^L
/*************************************************************************
 *
 * NAME
 *	ps_init - prepare to map postscript output
 *
 * PARAMETERS
 *	none.
 *
 * DESCRIPTION
 *	Copies the prologue file to the stdout, in preparation for world
 *	mapping.  This file sets up functions used later and prints
 *	the underlying hex grid.
 *
 * RETURN VALUE
 *	void
 *
 * CAVEATS
 *	None.
 *
 *************************************************************************/

void
ps_init()
{
    FILE *fp;
    char s[LINE_SIZE];

    if ((fp = fopen(PS_PROLOGUE, "r")) == NULL) {
	perror(PS_PROLOGUE);
	exit(1);
    }

    while (fgets(s, sizeof(s), fp) != NULL) {
	(void)fputs(s, stdout);
    }

    (void)fclose(fp);
}

^L
/*************************************************************************
 *
 * NAME
 *	ps_map - map worlds into postscript output
 *
 * PARAMETERS
 *	s - system to put out
 *
 * DESCRIPTION
 *	Emits the appropriate postscript commands to render the system
 *	in its hex.
 *
 * RETURN VALUE
 *	void
 *
 * CAVEATS
 *	None.
 *
 *************************************************************************/

void
ps_map(s)
struct sys *s;
{
    char *u;

    printf("%2d %2d mapCoords \n", s->x, s->y);

    switch (s->zone) {
    case 'A':
	printf("amberZone \n");
	break;
    case 'R':
	printf("redZone \n");
	break;
    }

    printf("(%.2d%.2d) hexNumber \n", s->x, s->y);

    if (s->uwp[1] == '0') {
	printf("asteroids \n");
    }
    else if (s->uwp[3] == '0') {
	printf("desPlnt \n");
    }
    else {
	printf("liqPlnt \n");
    }

    u = s->trade;
    if (u = strchr(u, 'H')) {
	if (u[1] == 'i' || u[1] == 'I') {
	   capitalize(s->name);
	}
    } else if (s->uwp[4] == '9' || s->uwp[4] == 'A') {
       capitalize(s->name);
    }
    printf("(%s) name \n", s->name);

    printf("(%c) starPort \n", s->uwp[0]);

    if (s->base == 'N' || s->base == 'A') {
	printf("navalBase \n");
    }
    if (s->base == 'S' || s->base == 'A') {
	printf("scoutBase \n");
    }

    if (s->gas > 0) {
	printf("gasGiant \n");
    }

    printf("\n");
}

^L
/*************************************************************************
 *
 * NAME
 *	ps_finish - complete postscript output
 *
 * PARAMETERS
 *	none.
 *
 * DESCRIPTION
 *	emits the final postscript command which causes the page to be
 *	printed.
 *
 * RETURN VALUE
 *	void
 *
 * CAVEATS
 *	None.
 *
 *************************************************************************/

void
ps_finish()
{
    printf("showpage \n");
}
//E*O*F mapsub.c//

echo x - mapsub.hex
cat > "mapsub.hex" << '//E*O*F mapsub.hex//'
   ______            ______            ______            ______
  /      \          /      \          /      \          /      \
 /        \        /        \        /        \        /        \
/          \______/          \______/          \______/          \______
\          /      \          /      \          /      \          /      \
 \        /        \        /        \        /        \        /        \
  \______/          \______/          \______/          \______/          \
  /      \          /      \          /      \          /      \          /
 /        \        /        \        /        \        /        \        /
/          \______/          \______/          \______/          \______/
\          /      \          /      \          /      \          /      \
 \        /        \        /        \        /        \        /        \
  \______/          \______/          \______/          \______/          \
  /      \          /      \          /      \          /      \          /
 /        \        /        \        /        \        /        \        /
/          \______/          \______/          \______/          \______/
\          /      \          /      \          /      \          /      \
 \        /        \        /        \        /        \        /        \
  \______/          \______/          \______/          \______/          \
  /      \          /      \          /      \          /      \          /
 /        \        /        \        /        \        /        \        /
/          \______/          \______/          \______/          \______/
\          /      \          /      \          /      \          /      \
 \        /        \        /        \        /        \        /        \
  \______/          \______/          \______/          \______/          \
  /      \          /      \          /      \          /      \          /
 /        \        /        \        /        \        /        \        /
/          \______/          \______/          \______/          \______/
\          /      \          /      \          /      \          /      \
 \        /        \        /        \        /        \        /        \
  \______/          \______/          \______/          \______/          \
  /      \          /      \          /      \          /      \          /
 /        \        /        \        /        \        /        \        /
/          \______/          \______/          \______/          \______/
\          /      \          /      \          /      \          /      \
 \        /        \        /        \        /        \        /        \
  \______/          \______/          \______/          \______/          \
  /      \          /      \          /      \          /      \          /
 /        \        /        \        /        \        /        \        /
/          \______/          \______/          \______/          \______/
\          /      \          /      \          /      \          /      \
 \        /        \        /        \        /        \        /        \
  \______/          \______/          \______/          \______/          \
  /      \          /      \          /      \          /      \          /
 /        \        /        \        /        \        /        \        /
/          \______/          \______/          \______/          \______/
\          /      \          /      \          /      \          /      \
 \        /        \        /        \        /        \        /        \
  \______/          \______/          \______/          \______/          \
  /      \          /      \          /      \          /      \          /
 /        \        /        \        /        \        /        \        /
/          \______/          \______/          \______/          \______/
\          /      \          /      \          /      \          /      \
 \        /        \        /        \        /        \        /        \
  \______/          \______/          \______/          \______/          \
  /      \          /      \          /      \          /      \          /
 /        \        /        \        /        \        /        \        /
/          \______/          \______/          \______/          \______/
\          /      \          /      \          /      \          /      \
 \        /        \        /        \        /        \        /        \
  \______/          \______/          \______/          \______/          \
         \          /      \          /      \          /      \          /
          \        /        \        /        \        /        \        /
           \______/          \______/          \______/          \______/
//E*O*F mapsub.hex//

echo x - mapsub.pro
cat > "mapsub.pro" << '//E*O*F mapsub.pro//'
%!PS-Adobe-1.0
% Traveller subsector map and mapping functions

%-----Constants-----
/cm { 72 mul 2.54 div } def     % cm >> points
/unit { 1 cm mul } def


/topOfPageX 4.5 cm def
/topOfPageY 25 cm def
/nameFontSize 9 def
/nameWidthLimit 1.9 unit def

/nameFont /Times-Roman findfont nameFontSize scalefont def
/portFont /Helvetica findfont 10 scalefont def
/numberFont /Helvetica findfont 8 scalefont def

%-----Basic Functions-----
/hex {                             % - >> -
  gsave
  -1 unit 0 rmoveto
  currentpoint translate
  60 rotate
  5 {
    1 unit 0 lineto
    currentpoint translate
    -60 rotate
  } repeat
  closepath
  stroke
  grestore
} def

/rowOfHex {                       % x y >> -
  moveto
  10 {
    hex
    0 0 3 sqrt unit sub rmoveto
  } repeat
} def

/hexMap {                         % - >> -
  .3 setlinewidth
  /curX topOfPageX def
  /curY topOfPageY def
  4 {
    curX curY rowOfHex
    /curX curX 1.5 unit add def
    /curY curY 3 sqrt 2 div unit sub def
    curX curY rowOfHex
    /curX curX 1.5 unit add def
    /curY curY 3 sqrt 2 div unit add def
  } repeat
} def

/mapCoords {                   % HexX HexY >> -
  /actY exch 1 sub 10 mod 3 sqrt unit mul topOfPageY exch sub def
  dup 2 mod 0 eq {
    /actY actY 3 sqrt 2 div unit sub def    % displace column if HexX is even
  } if
  /actX exch 1 sub 8 mod 1.5 unit mul topOfPageX add def
} def

/getCoords {                   % - >> x y
  actX actY
} def

/liqPlnt {
  newpath
  getCoords .1 unit 0 360 arc fill
} def

/desPlnt {
  gsave
  newpath
  getCoords .1 unit 0 360 arc
  gsave
  1 setgray fill
  grestore
  .5 setlinewidth stroke
  grestore
} def

/asteroids {
  newpath
  getCoords .1 unit add .04 unit 0 360 arc fill
  getCoords exch .15 unit add exch .02 unit 0 360 arc fill
  getCoords .15 unit sub exch .1 unit add exch .03 unit 0 360 arc fill
  getCoords .04 unit sub exch .15 unit sub exch .05 unit 0 360 arc fill
  getCoords .05 unit sub .02 unit 0 360 arc fill
} def

/name {                   %  name >> -
  getCoords moveto
  nameFont setfont
  gsave
  0 -.55 unit rmoveto
  dup stringwidth pop
  dup dup nameWidthLimit gt
    {nameWidthLimit exch div 1 scale}
    {pop}
  ifelse
  neg 2 div 0 rmoveto
  gsave
  0 nameFontSize -6 div rmoveto
  dup stringwidth pop 0 rlineto
  0 nameFontSize rlineto
  dup stringwidth pop neg 0 rlineto
  closepath
  1 setgray fill
  grestore
  show
  grestore
} def

/starPort {                % code >> -
  getCoords moveto
  portFont setfont
  dup stringwidth pop 2 div 0 exch sub
    .2 unit rmoveto
  show
} def

/navalBase {               % - >> -
  gsave
  getCoords moveto
  -.5 unit .3 unit rmoveto
  currentpoint translate
  4 {
    .2 unit 0 lineto
    currentpoint translate
    -144 rotate
  } repeat
  closepath
  fill
  grestore
} def

/scoutBase {
  gsave
  newpath
  getCoords moveto
  -.5 unit -.125 unit rmoveto
  currentpoint translate
  60 rotate
  .15 unit 0 lineto
  currentpoint translate
  -120 rotate
  .15 unit 0 lineto
  closepath
  fill
  grestore
} def

/gasGiant {
  gsave
  newpath
  getCoords moveto
  .4 unit .3 unit rmoveto
  currentpoint translate
  0 0 .05 unit 0 360 arc fill
  grestore
} def

/redZone {
  newpath
  .8 setgray
  getCoords 2 3 div unit 0 360 arc fill
  0 setgray
} def

/amberZone {
  gsave
  newpath
  .7 setlinewidth
  0 setgray
  getCoords 2 3 div unit 0 360 arc stroke
  grestore
} def

/hexNumber {                 % (XX YY) >> -
  getCoords moveto
  numberFont setfont
  dup stringwidth pop 2 div 0 exch sub
    .6 unit rmoveto
  show
} def

%-----Main-----
hexMap
% Other system specs  (start with zones)
//E*O*F mapsub.pro//

exit 0

The Traveller Mailing List is a courtesy of James Perkins and Tektronix, Inc.
All opinions and material above is the responsibility of the originator.
Send Submissions To: @RELAY.CS.NET:traveller@dadla.LA.TEK.COM,
	uunet!dadla.la.tek.com!traveller, or traveller@dadla.la.tek.com
List Administrator: traveller-request@dadla.la.tek.com

-------- End of TML Messages --------

